﻿using System;
using System.Collections.Generic;
using System.Text;
using HR.Appointments.DataLayer;
using HR.Appointments.Service.Tools;
using HR.Appointments.Service.ValueObjects;

namespace HR.Appointments.Service
{
    /// <summary>
    /// Entity class for open hour per day.
    /// </summary>
    public class OpenHoursEntity
    {
        #region Member variable
        private int _companyId;
        private int _dayId; 
        private string _name;
        private TimeUnit _fromTime = TimeUnit.Create(0, 0);
        private TimeUnit _toTime = TimeUnit.Create(0, 0);
        private CompanyEntity _company;
        #endregion

        #region Constructors
        private OpenHoursEntity(int companyId, int dayId,  
            TimeUnit fromTime, TimeUnit toTime)
        {
            _companyId = companyId;
            _dayId = dayId;
            _name = DateUtils.IntToDayOfWeekIceland(dayId).ToString();
            _fromTime = fromTime;
            _toTime = toTime;
            _company = DAO.Instance.Company.GetInstance(companyId);

            System.Diagnostics.Debug.Assert(_company != null, "Company in openHours is Null");
        }
        #endregion

        #region Properties
        /// <summary>
        /// Day of week identifier
        /// </summary>
        public int DayId
        {
            get
            {
                return _dayId; 
            }
            set
            {
                _dayId = value; 
            }
        }

        /// <summary>
        /// Company identifier
        /// </summary>
        public int CompanyId
        {
            get
            {
                return _companyId;
            }
            set
            {
                _companyId = value;
            }
        }

        /// <summary>
        /// The name of the day
        /// </summary>
        public string Name
        {
            get
            {
                return _name; 
            }
            set
            {
                _name = value; 
            }
        }

        /// <summary>
        /// When the company opens for this day
        /// </summary>
        public TimeUnit FromTime
        {
            get
            {
                return _fromTime; 
            }
            set
            {
                _fromTime = value; 
            }
        }

        /// <summary>
        /// When the company closes for this day
        /// </summary>
        public TimeUnit ToTime
        {
            get
            {
                return _toTime; 
            }
            set
            {
                _toTime = value; 
            }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Get the calculated timeslots for this day
        /// </summary>
        /// <returns></returns>
        public List<TimeUnit> GetTimeSlots()
        {
            var result = new List<TimeUnit>();
            var currentTime = (TimeUnit)_fromTime.Clone();
            while (currentTime.CompareTo(_toTime) < 0)
            {
                result.Add((TimeUnit)currentTime.Clone());
                currentTime.Add(_company.SlotDuration);
            }
            
            return result;
        }
        #endregion

        #region Internal Methods
        /// <summary>
        /// Convert this object to datalayer 
        /// </summary>
        /// <param name="data">Datalayer entity</param>
        /// <returns>A datalayer entity with this objects values</returns>
        internal OpenHour ToData(OpenHour data)
        {
            if (data == null)
            {
                data = new OpenHour();
            }
            data.CloseHour = _toTime.Hour;
            data.CloseMinute = _toTime.Minute;
            data.CompanyId = _companyId;
            data.DayId = _dayId;
            data.OpenHour1 = _fromTime.Hour;
            data.OpenMinute = _fromTime.Minute;

            return data;
        }
        #endregion

        #region Override Members
        /// <summary>
        /// Determines whether the specified Object is equal to the current Object.
        /// </summary>
        /// <param name="obj">The Object to compare with the current Object.</param>
        /// <returns>true if the specified Object is equal to the current Object; otherwise, false.</returns>
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType()) return false;
            OpenHoursEntity eql = (OpenHoursEntity)obj;
            return (eql.CompanyId == CompanyId && eql.DayId == DayId);
        }

        /// <summary>
        /// Serves as a hash function for a this type.
        /// </summary>
        /// <returns>A hash code for the current Object.</returns>
        public override int GetHashCode()
        {
            return _companyId.GetHashCode() ^ _dayId.GetHashCode();
        }

        /// <summary>
        /// Returns a String that represents the current Object.
        /// </summary>
        /// <returns>A String that represents the current Object.</returns>
        public override string ToString()
        {
            return DateUtils.IntToDayOfWeek(_dayId).ToString() + " " + FromTime.ToString() + " - " + ToTime.ToString();
        }
        #endregion

        #region Static Members
        /// <summary>
        /// Loads a datalayer entity into a service entity.
        /// </summary>
        /// <param name="row"></param>
        /// <returns>A loaded entity</returns>
        internal static OpenHoursEntity Load(HR.Appointments.DataLayer.OpenHour row)
        {
            if (row == null) return null;
            return new OpenHoursEntity(row.CompanyId, row.DayId,
                TimeUnit.Create(row.OpenHour1, row.OpenMinute), 
                TimeUnit.Create(row.CloseHour, row.CloseMinute));
        }

        /// <summary>
        /// Creates a new entity
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <param name="dayId">Idetification of the day 1=Monday...7=Sunday</param>
        /// <param name="fromTime">When the company opens this day</param>
        /// <param name="toTime">When the company closes this day</param>
        /// <returns></returns>
        public static OpenHoursEntity Create(int companyId, int dayId,
            TimeUnit fromTime, TimeUnit toTime)
        {
            return new OpenHoursEntity(companyId, dayId, fromTime, toTime);
        }
        #endregion
    }
}
